<html>
<head><meta charset="utf-8"><title>Code Examination: slice casting (~20 significant lines) · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html">Code Examination: slice casting (~20 significant lines)</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="168719985"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168719985" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168719985">(Jun 21 2019 at 21:55)</a>:</h4>
<p>Well since it seems like we're going to try posting unsafe code here for review, this is a small and simple test case for this process.</p>
<p>I've got a "slice cast with possible resizing of the slice" function. Normal thing you might write. This is motivated by the fact that <code>gfx-hal</code> had a similar function in <code>0.1</code>, and it had lurking UB, and then it was reported (including the fixed code) and they still have the exact same function in <code>0.2</code>. I wanted to make a version of this that's as bulletproof as possible, so here we are.</p>
<p>You can read the code as a PR <a href="https://github.com/Lokathor/lokacore/pull/1" target="_blank" title="https://github.com/Lokathor/lokacore/pull/1">here</a> or just as a plain file <a href="https://github.com/Lokathor/lokacore/blob/cast_slice/src/lib.rs" target="_blank" title="https://github.com/Lokathor/lokacore/blob/cast_slice/src/lib.rs">here</a>. The function in question is <code>try_cast_slice</code>. There's also <code>try_cast_slice_mut</code> of course.</p>



<a name="168747798"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168747798" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168747798">(Jun 22 2019 at 11:30)</a>:</h4>
<p>So basically this is transmuting around slices of types where the validity invariant allows any (or any initialized, decision still pending) bit pattern. That seems fine for all the integer and floating point types.</p>



<a name="168747809"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168747809" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168747809">(Jun 22 2019 at 11:31)</a>:</h4>
<p>For <code>Option&lt;NonZero*&gt;</code> you are relying on it being safe to transmute that back and forth to the equally-sized integer type, which I am not sure is a guarantee we are making.</p>



<a name="168747851"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168747851" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168747851">(Jun 22 2019 at 11:32)</a>:</h4>
<p>the same goes for the <code>Zeroed</code> part btw</p>



<a name="168747857"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168747857" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168747857">(Jun 22 2019 at 11:33)</a>:</h4>
<p>it sounds like a fairly reasonable guarantee though -- we do IIRC guarantee the similar thing for <code>Option&lt;&amp;T&gt;</code>, so seems reasonable to also guarantee it for <code>Option&lt;NonZero*&gt;</code></p>



<a name="168747868"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168747868" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168747868">(Jun 22 2019 at 11:33)</a>:</h4>
<p>btw, I think you could restrict the ZST restriction a bit</p>



<a name="168747909"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168747909" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168747909">(Jun 22 2019 at 11:34)</a>:</h4>
<p>transmuting an empty slice of any type to a slice of ZST is fine (you can pick any length so, so that might be a bit arbitrary)</p>



<a name="168747916"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168747916" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168747916">(Jun 22 2019 at 11:34)</a>:</h4>
<p>and vice versa you could transmute a slice of ZST to an empty slice of any type</p>



<a name="168747920"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168747920" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168747920">(Jun 22 2019 at 11:34)</a>:</h4>
<p>(both assuming that you checked for alignment first, as you do)</p>



<a name="168748336"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168748336" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168748336">(Jun 22 2019 at 11:50)</a>:</h4>
<p>NonZeroT is guaranteed to have the same representation as T and at least with the current implementatoin Option&lt;NonZeroT&gt; is also guaranteed to have the same representation as NonZeroT.</p>



<a name="168748402"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168748402" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168748402">(Jun 22 2019 at 11:51)</a>:</h4>
<p>Documentation at least specifies that <code>size_of::&lt;Option&lt;NonZeroT&gt; &gt; == size_of::&lt;T&gt;</code>.</p>



<a name="168748833"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168748833" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> centril <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168748833">(Jun 22 2019 at 12:04)</a>:</h4>
<p>The semi-formal rules are given in <a href="https://github.com/rust-lang/rust/pull/60300" target="_blank" title="https://github.com/rust-lang/rust/pull/60300">https://github.com/rust-lang/rust/pull/60300</a> which defined the behavior.</p>



<a name="168752247"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168752247" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168752247">(Jun 22 2019 at 13:59)</a>:</h4>
<p><span class="user-mention" data-user-id="120791">@RalfJ</span> we could add the <code>NonZero_</code> types to the layout of scalars, and also consider them when defining the validity of scalars</p>



<a name="168752294"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168752294" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168752294">(Jun 22 2019 at 14:00)</a>:</h4>
<p>same applies to <code>NonNull&lt;T&gt;</code>, we probably want to add it to the layout of pointers and references section</p>



<a name="168752356"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168752356" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168752356">(Jun 22 2019 at 14:02)</a>:</h4>
<p>the rest is covered in: <a href="https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/layout/enums.md#discriminant-elision-on-option-like-enums" target="_blank" title="https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/layout/enums.md#discriminant-elision-on-option-like-enums">https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/layout/enums.md#discriminant-elision-on-option-like-enums</a></p>



<a name="168752360"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168752360" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168752360">(Jun 22 2019 at 14:02)</a>:</h4>
<p>we might want to update that section, e.g., to point to the PR that <span class="user-mention" data-user-id="126931">@centril</span> mentioned, since that kind of RFC'ed part of this behavior</p>



<a name="168753097"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168753097" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168753097">(Jun 22 2019 at 14:27)</a>:</h4>
<p>so I've sent a PR expanding the discriminant-elision optimization with the PR that <span class="user-mention" data-user-id="126931">@centril</span> mentioned: <a href="https://github.com/rust-lang/unsafe-code-guidelines/pull/149" target="_blank" title="https://github.com/rust-lang/unsafe-code-guidelines/pull/149">https://github.com/rust-lang/unsafe-code-guidelines/pull/149</a></p>



<a name="168753139"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168753139" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> gnzlbg <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168753139">(Jun 22 2019 at 14:28)</a>:</h4>
<p>We don't need to say anything about the layout of <code>NonZero_</code> or <code>NonNull</code> in the UCGs, because they are <code>repr(transparent)</code>.</p>



<a name="168783003"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168783003" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168783003">(Jun 23 2019 at 07:32)</a>:</h4>
<p>Yeah, ZST is kinda weird in this situation. Just deciding that ZST can only cast to other ZST seemed like the simplest answer that wouldn't cause accidental surprise later on.</p>



<a name="168786233"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168786233" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168786233">(Jun 23 2019 at 09:17)</a>:</h4>
<blockquote>
<p>We don't need to say anything about the layout of <code>NonZero_</code> or <code>NonNull</code> in the UCGs, because they are <code>repr(transparent)</code>.</p>
</blockquote>
<p>yeah, it's <code>Option&lt;_&gt;</code> of those that I was worried about</p>



<a name="168786279"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168786279" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168786279">(Jun 23 2019 at 09:18)</a>:</h4>
<blockquote>
<p>Yeah, ZST is kinda weird in this situation. Just deciding that ZST can only cast to other ZST seemed like the simplest answer that wouldn't cause accidental surprise later on.</p>
</blockquote>
<p>that's certainly a safe choice, just wanted to make sure you are aware that you have some more leeway there. also kudos for checking alignment first, many people forget that there can be ZST with non-trivial alignment constraints.</p>



<a name="168794454"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code%20Examination%3A%20slice%20casting%20%28%7E20%20significant%20lines%29/near/168794454" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Code.20Examination.3A.20slice.20casting.20(~20.20significant.20lines).html#168794454">(Jun 23 2019 at 13:34)</a>:</h4>
<p>A lot of this was hammered out with <span class="user-mention" data-user-id="125270">@scottmcm</span> , who suggested for example to split off <code>Zeroable</code> as its own trait which a person might want to utilize separate from <code>Pod</code>.</p>
<p>I settled on ZST and non-ZST not converting between each other because that way, if you get a slice back, you can always round trip it and get the slice you started with. It's not explicitly spelled out as a guarantee, but it really "make sense" as a thing that should generally work. If a ZST is involved then non-ZST -&gt; ZST lets you preserve the length you'd have absolutely no way to know that's actually "correct" for the current memory situation, so when you go from ZST -&gt; non-ZST you'd have to just say that the output length is 0 and you've "lost" some information.</p>
<p>It's 7AM here right now, and I'll leave the PR up until some time around 12 hours from now. People can of course leave a comment here or there after the PR is merged as well.</p>
<p>I think we can call this a moderately successful test run of the unsafe code reviewing. No bugs detected but we spotted at least one place to expand/clarify the guidelines it seems.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>